package top.whsu.FileServer;

import top.whsu.FileServer.utils.*;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class Server extends ServerSocket {

    private String baseFolder;

    private int threadCnt;

    private int connected, maxConnection;

    public Server(int portNum, String baseFolder, int maxConnection) throws IOException {
        super(portNum);
        this.baseFolder = baseFolder;
        this.threadCnt = 0;
        this.maxConnection = maxConnection;
        this.connected = 0;
    }

    /**
     * outer interface
     */
    public void load() throws IOException {
        while (true) {
            Socket clientSocket = super.accept();
            while (this.connected>=this.maxConnection) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            new Thread(new FileTransmitTask(clientSocket)).start();
        }
    }

    /**
     * using multi-threading
     */
    class FileTransmitTask implements Runnable {

        private Socket clientSocket;

        private byte[] buffer = new byte[1024];

        private int id;

        private String getFileName() {
            Date now = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
            return formatter.format(now);
        }

        public FileTransmitTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
            this.id = threadCnt++;
        }

        public void run() {
            try {
                String filenameString = getFileName();
                connected++;
                InputStream fileDownloadStream = this.clientSocket.getInputStream();
                OutputStream fileWriteStream = new FileOutputStream(baseFolder+filenameString);
                DataOutputStream logger = new DataOutputStream(this.clientSocket.getOutputStream());

                int readsize = 0;
                int receivedSize = 0;

                System.out.printf("id %d: Started Receiving File \"%s\"\n", this.id, filenameString);
                while ((readsize = fileDownloadStream.read(buffer, 0, buffer.length)) != -1) {
                    fileWriteStream.write(buffer, 0, readsize);
                    receivedSize += readsize;
                    logger.writeInt(receivedSize);
                    // System.out.printf("id %d: Receiving... size %s\n", this.id, DataSizeFormat.format(receivedSize));
                }
                System.out.printf("id %d: File \"%s\" Received. Size: %s\n", this.id, filenameString, DataSizeFormat.format(receivedSize));

                logger.close();
                fileWriteStream.close();
                fileDownloadStream.close();
                connected--;
            } catch (IOException e) {
                e.printStackTrace();
                connected--;
            }
        }
    }
}
